#pragma once

#include"Common.h"

#include"ProductionTask.h"
#include"MacroSearcher.h"

class ProductionManagerClass
{
public:
	ProductionManagerClass()
		:_waitFrame(0)
	{
	}
	void OnFrame()
	{
		if(_waitFrame > 0)
		{
			--_waitFrame;
			if(_waitFrame > 0)
			{
				return;
			}
		}

		if(_tasks.size() > 0)
		{
			ProductionTask& taskHead((*_tasks.begin()));
			if(taskHead.GetTaskType() == ProductionTask::Build)
			{
				if(taskHead.GetState() == ProductionTask::WaitForCanMake)
				{
					UnitControlerManager::Instance().Build(taskHead);
				}
				else if(taskHead.GetState() == ProductionTask::Asigned)
				{
				}
				else if(taskHead.GetState() == ProductionTask::Depart)
				{
				}
				else if(taskHead.GetState() == ProductionTask::Morphing)
				{
					_tasks.erase(_tasks.begin());
				}
				else if(taskHead.GetState() == ProductionTask::Dead)
				{
					UnitControlerManager::Instance().Build(taskHead);
				}
			}
			else if(taskHead.GetTaskType() == ProductionTask::CreateUnit)
			{
				if(Broodwar->self()->minerals() >= taskHead.GetBuildType().mineralPrice() && Broodwar->self()->gas() >= taskHead.GetBuildType().gasPrice())
				{
					if(taskHead.GetBuildType() == UnitTypes::Zerg_Lair || taskHead.GetBuildType() == UnitTypes::Zerg_Hive)
					{
						Unit* hatchery = Info::Instance().GetBaseInfo(0)->GetHatchery();
						if(Broodwar->canMake(hatchery , taskHead.GetBuildType()))
						{
							hatchery->morph(taskHead.GetBuildType());
							_tasks.erase(_tasks.begin());
							goto END;
						}
					}
					else
					{
						UnitType originalType;
						if(taskHead.GetBuildType() == UnitTypes::Zerg_Lurker)
						{
							originalType = UnitTypes::Zerg_Hydralisk;
						}
						else
						{
							originalType = UnitTypes::Zerg_Larva;
						}

						for each(Unit* whichUnit in Broodwar->self()->getUnits())
						{
							if(whichUnit->getType() == originalType)
							{
								if(Broodwar->canMake(whichUnit , taskHead.GetBuildType()))
								{
									whichUnit->morph(taskHead.GetBuildType());
									_tasks.erase(_tasks.begin());
									goto END;
								}
							}
						}
					}
				}
			}
			else if(taskHead.GetTaskType() == ProductionTask::Research)
			{
				UnitType researcherType = taskHead.GetTechType().whatResearches();
				if(Broodwar->self()->minerals() >= taskHead.GetTechType().mineralPrice() && Broodwar->self()->gas() >= taskHead.GetTechType().gasPrice())
				{
					for each(Unit* whichUnit in Broodwar->self()->getUnits())
					{
						if(whichUnit->getType() == researcherType)
						{
							if(Broodwar->canResearch(whichUnit , taskHead.GetTechType()))
							{
								whichUnit->research(taskHead.GetTechType());
								_tasks.erase(_tasks.begin());
								goto END;
							}
						}
					}
				}
			}
			else if(taskHead.GetTaskType() == ProductionTask::Upgrade)
			{
				if(Broodwar->self()->minerals() >= taskHead.GetUpgradeType().mineralPrice() && Broodwar->self()->gas() >= taskHead.GetUpgradeType().gasPrice())
				{
					UnitType researcherType = taskHead.GetUpgradeType().whatUpgrades();
					for each(Unit* whichUnit in Broodwar->self()->getUnits())
					{
						if(whichUnit->getType() == researcherType)
						{
							if(Broodwar->canUpgrade(whichUnit , taskHead.GetUpgradeType()))
							{
								whichUnit->upgrade(taskHead.GetUpgradeType());
								_tasks.erase(_tasks.begin());
								goto END;
							}
						}
					}
				}
			}
		}
		else
		{
			if(Broodwar->getFrameCount() > 1000)
			{
				list<ProductionTask> t;
				t.push_back(SimpleRuleBaseProduction());
				AddTasks(t);
			}
		}
		goto END2;
END:
		_waitFrame = 5;
END2:
		Draw();
	}
	void AddTasks(const list<ProductionTask>& newTasks)
	{
		_tasks.insert(_tasks.end() , newTasks.begin() , newTasks.end());
	}
	bool TasksAreInvalid() const
	{
		return true;
	}
	ProductionTask SearchTest()
	{
		Macro::Searcher testSearcher;
		ProductionTask t(testSearcher.AlphaBeta(600));
		if(t.GetTaskType() == ProductionTask::CreateUnit || t.GetTaskType() == ProductionTask::Build)
		{
			Broodwar->printf("%s" , t.GetBuildType().getName().c_str());
		}
		return t;
	}
	ProductionTask SimpleRuleBaseProduction()
	{
		ProductionTask answer;

		if(Broodwar->self()->supplyTotal() - Broodwar->self()->supplyUsed() < 6)
		{
			answer = ProductionTask(UnitTypes::Zerg_Overlord);
		}
		else
		{
			answer = ProductionTask(UnitTypes::Zerg_Zergling);
		}

		return answer;
	}

private:
	void Draw()
	{
		int y = 50;
		Broodwar->drawTextScreen(10 , y , "TASKS");
		y += 10;
		for(list<ProductionTask>::iterator it = _tasks.begin() ; it != _tasks.end() ; ++it)
		{
			Broodwar->drawTextScreen(10 , y , "%s" , (*it).GetName().c_str());
			y += 8;
		}
	}
	//--
	list<ProductionTask> _tasks;
	int _waitFrame;
};

typedef Singleton<ProductionManagerClass> ProductionManager;